/* ================================================================== * DerbyDataSourceFactory.java - Jun 27, 2011 11:26:59 AM * * Copyright 2007-2011 SolarNetwork.net Dev Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * ================================================================== */ package net.solarnetwork.org.apache.derby; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.sql.Driver; import java.sql.SQLException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Properties; import javax.sql.ConnectionPoolDataSource; import javax.sql.DataSource; import javax.sql.XADataSource; import org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource; import org.apache.derby.jdbc.EmbeddedDataSource; import org.apache.derby.jdbc.EmbeddedDriver; import org.apache.derby.jdbc.EmbeddedXADataSource; import org.osgi.service.jdbc.DataSourceFactory; /** * DataSourceFactory for Apache Derby. * * @author matt * @version 1.0 */ public class DerbyDataSourceFactory implements DataSourceFactory { @Override public DataSource createDataSource(Properties props) throws SQLException { EmbeddedDataSource ds = new EmbeddedDataSource(); configureDataSourceProperties(ds, props); return ds; } @Override public ConnectionPoolDataSource createConnectionPoolDataSource(Properties props) throws SQLException { EmbeddedConnectionPoolDataSource ds = new EmbeddedConnectionPoolDataSource(); configureDataSourceProperties(ds, props); return ds; } @Override public XADataSource createXADataSource(Properties props) throws SQLException { EmbeddedXADataSource ds = new EmbeddedXADataSource(); configureDataSourceProperties(ds, props); return ds; } @Override public Driver createDriver(Properties props) throws SQLException { Driver driver = new EmbeddedDriver(); configureDataSourceProperties(driver, props); return driver; } private void configureDataSourceProperties(Object object, Properties props) throws SQLException { if ( props == null ) { return; } Enumeration<?> enumeration = props.keys(); while ( enumeration.hasMoreElements() ) { String name = (String) enumeration.nextElement(); // special support for "url" if ( "url".equals(name) ) { String jdbcUrl = props.getProperty(name); if ( !jdbcUrl.startsWith("jdbc:") ) { throw new SQLException("URL does not start with 'jdbc:'"); } jdbcUrl = jdbcUrl.substring(5); try { URI uri = new URI(jdbcUrl); String dbName = uri.getSchemeSpecificPart(); String connAttributes = null; int splitIndex = dbName.indexOf(';'); if ( splitIndex != -1 ) { if ( splitIndex < (dbName.length() - 1) ) { connAttributes = dbName.substring(splitIndex + 1); } dbName = dbName.substring(0, splitIndex); } setProperty(object, "databaseName", dbName); if ( connAttributes != null ) { setProperty(object, "connectionAttributes", connAttributes); } } catch ( URISyntaxException e ) { throw new SQLException("Unparsable 'url' property", e); } } else { setProperty(object, name, props.getProperty(name)); } } } protected void throwSQLException(Exception cause, String theType, String value) throws SQLException { SQLException sqlException = new SQLException("Invalid " + theType + " value: " + value); sqlException.initCause(cause); throw sqlException; } protected Object toBasicType(String value, String type) throws SQLException { if ( value == null ) { return null; } else if ( type == null || type.equals(String.class.getName()) ) { return value; } else if ( type.equals(Integer.class.getName()) || type.equals(int.class.getName()) ) { try { return Integer.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Integer", value); } } else if ( type.equals(Float.class.getName()) || type.equals(float.class.getName()) ) { try { return Float.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Float", value); } } else if ( type.equals(Long.class.getName()) || type.equals(long.class.getName()) ) { try { return Long.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Long", value); } } else if ( type.equals(Double.class.getName()) || type.equals(double.class.getName()) ) { try { return Double.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Double", value); } } else if ( type.equals(Character.class.getName()) || type.equals(char.class.getName()) ) { if ( value.length() != 1 ) { throw new SQLException("Invalid Character value: " + value); } return new Character(value.charAt(0)); } else if ( type.equals(Byte.class.getName()) || type.equals(byte.class.getName()) ) { try { return Byte.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Byte", value); } } else if ( type.equals(Short.class.getName()) || type.equals(short.class.getName()) ) { try { return Short.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Short", value); } } else if ( type.equals(Boolean.class.getName()) || type.equals(boolean.class.getName()) ) { try { return Boolean.valueOf(value); } catch ( NumberFormatException e ) { throwSQLException(e, "Boolean", value); } } else { throw new SQLException("Invalid property type: " + type); } return null; } protected void setProperty(Object object, String name, String value) throws SQLException { Class<?> type = object.getClass(); java.beans.PropertyDescriptor[] descriptors; try { descriptors = java.beans.Introspector.getBeanInfo(type).getPropertyDescriptors(); } catch ( Exception exc ) { SQLException sqlException = new SQLException(); sqlException.initCause(exc); throw sqlException; } List<String> names = new ArrayList<String>(); for ( int i = 0; i < descriptors.length; i++ ) { if ( descriptors[i].getWriteMethod() == null ) { continue; } if ( descriptors[i].getName().equals(name) ) { Method method = descriptors[i].getWriteMethod(); Class<?> paramType = method.getParameterTypes()[0]; Object param = toBasicType(value, paramType.getName()); try { method.invoke(object, new Object[] { param }); } catch ( Exception exc ) { SQLException sqlException = new SQLException(); sqlException.initCause(exc); throw sqlException; } return; } names.add(descriptors[i].getName()); } throw new SQLException( "No such property: " + name + ", exists. Writable properties are: " + names); } }